package http;

import handler.Handler;
import util.MyUtil;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @author Karl
 * @Date 2023/1/1 - 20:31
 */
public class MyHttpRequest {

    private static Charset utf_8 = StandardCharsets.UTF_8;

    private static String lineSeparator = System.lineSeparator();

    private byte[] lineByte = lineSeparator.getBytes(utf_8);

    private String requestLine;

    private Map<String, String> requestHeader = new HashMap<>();
//    private StringBuilder requestBody = new StringBuilder();
    private List<Byte> requestBody = new LinkedList<>();

    private String host;
    private int port = 80;
    private String fromUrl;
    private String url;
    private HttpMethod method;

    private Handler handler = null;


    public MyHttpRequest() {
    }

    public String getRequestLine() {
        return requestLine;
    }

    public void setRequestLine(String line) {
        this.requestLine = line;
        String[] temp = line.split("\\s+");
        method = HttpMethod.get(temp[0]);
        //替换，为了保证在保存文件到磁盘中不出现命名冲突
        url = temp[1].replace("http://","").replace(":","@").replace("?","__");

    }

    public String getRequestHeader(String header) {
        return requestHeader.getOrDefault(header, null);
    }

    public void addRequestHeader(String header) {
        int idx = header.indexOf(':');
        if (idx != -1) {
            String headerName = header.substring(0, idx);
            if (headerName.equals("Host")) {
                String temp = header.substring(idx + 1);
                int idx2 = temp.indexOf(':');
                if (idx2 != -1) {
                    host = temp.substring(1, idx2).trim();
                    port = Integer.parseInt(temp.substring(idx2+1).trim());
                } else
                    host = temp.substring(1).trim();
            }else if(headerName.equals("Proxy-Connection")){
                headerName = "Connection";
                header = header.replace("Proxy-Connection","Connection");
            }

            requestHeader.put(headerName, header);
        }
    }

    public byte[] getRequestBody() {
        byte[] ret = new byte[requestBody.size()];
        Iterator<Byte> it = requestBody.iterator();
        int idx = 0;
        while(it.hasNext()){
            ret[idx++] = it.next();
        }
        return ret;
    }

    public void addRequestBody(byte b) {
        this.requestBody.add(b);
    }

    public void addRequestBody(byte[] data,int len) {
        for (int i = 0; i < Math.min(data.length,len); i++) {
            requestBody.add(data[i]);
        }
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public Handler getHandler() {
        return handler;
    }

    public void setHandler(Handler handler) {
        this.handler = handler;
    }

    public HttpMethod getMethod() {
        return method;
    }

    public void setMethod(HttpMethod method) {
        this.method = method;
    }

    public String getFromUrl() {
        return fromUrl;
    }

    public void setFromIP(String fromUrl) {
        this.fromUrl = fromUrl;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public void sendOrigin(OutputStream rout,OutputStream lout) {
        //连接到目标服务器
        try {

            //根据HTTP method来判断是https还是http请求
            if (method==HttpMethod.CONNECT) {//https先建立隧道
                lout.write("HTTP/1.1 200 Connection Established\r\n\r\n".getBytes());
                lout.flush();
            }else{
                sendMessage(rout);
            }
        } catch (IOException e) {
            MyUtil.log("exception : %s %s", e.getClass(), e.getLocalizedMessage());
        }
    }

    private void sendMessage(OutputStream rout) throws IOException {
//        StringBuilder sb=  new StringBuilder();
        if (requestLine != null) {
//            sb.append(requestLine);
            rout.write(requestLine.getBytes());
        }

        for (String header : requestHeader.values()) {
//            sb.append(header);
            rout.write(header.getBytes());
        }
        rout.write(lineByte);
        if(requestBody.size()!=0){
            byte[] body = getRequestBody();
            rout.write(body);
//            sb.append(new String(body));
        }
        rout.flush();
//        System.out.println(sb);
    }

    public int getContentLength() {
        if(requestHeader.containsKey("Content-Length")){
            String header = requestHeader.get("Content-Length");
            int idx = header.indexOf(':');
            if(idx!=-1){
                //因为响应体格式是响应体名: (冒号+空格)响应头内容，所以+2
                return Integer.parseInt(header.substring(idx+2).trim());
            }

        }
        return -1;
    }

    public boolean isChunked() {
        if(requestHeader.containsKey("Transfer-Encoding")){
            String header = requestHeader.get("Transfer-Encoding");
            return header.contains("chunked");
        }
        return false;
    }

    public boolean cloneHeader(MyHttpRequest clone) {
        for (String header : requestHeader.values()) {
            clone.addRequestHeader(header);
        }
        return true;
    }
}
